﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Dispatcher;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;

namespace MF.ServiceModel
{
    public class IoCServiceHost : ServiceHost
    {
        public IoCServiceHost(Type svcType, params Uri[] baseAddresses)
            : base(svcType, baseAddresses)
        {

        }

        public IoCServiceHost(object singletonInstance, params Uri[] baseAddresses)
            : base(singletonInstance, baseAddresses)
        {

        }

        protected override void OnOpening()
        {
            this.Description.Behaviors.Add(new IoCServiceHostBehavior());
            base.OnOpening();
        }
    }

    public class IoCServiceHostBehavior : IServiceBehavior 
    {
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            foreach (var channelDispatcherBase in serviceHostBase.ChannelDispatchers)
            {
                var channelDispatcher = channelDispatcherBase as ChannelDispatcher;
                if (channelDispatcher != null)
                {
                    foreach (var endpointDispatcher in channelDispatcher.Endpoints)
                    {
                        endpointDispatcher.DispatchRuntime
                                          .InstanceProvider = new IoCInstanceProvider(serviceDescription.ServiceType);
                    }
                }
            }
        }
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {

        }
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {

        }
    }

    public class IoCInstanceProvider : IInstanceProvider
    {
        private readonly Type serviceType;

        public IoCInstanceProvider(Type serviceType)
        {
            this.serviceType = serviceType;
        }

        public object GetInstance(InstanceContext instanceContext)
        {
            return GetInstance(instanceContext, null);
        }
        public object GetInstance(InstanceContext instanceContext, Message message)
        {
            return IoC.Current.Container.Resolve(this.serviceType);
        }
        public void ReleaseInstance(System.ServiceModel.InstanceContext instanceContext, object instance)
        {
            if (instance is IDisposable)
                (instance as IDisposable).Dispose();
        }
    }



}
